﻿using AutoMapper;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using NFine.Data;
using NFine.Service.SystemManage;
using NFine.Service.WeixinManage;
using NFine.Util;
using NFine.Web.Filters;
using SharpRepository.Ioc.Microsoft.DependencyInjection;
using StackExchange.Redis;
using System;

namespace NFine.Web
{
    public class Startup
    {

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddStaticHttpContextAccessor();

            services.AddDistributedMemoryCache();//启用session之前必须先添加内存
            services.AddStackExchangeRedisCache(options => {
                options.Configuration = Configuration.GetConnectionString("RedisConnection");
                options.InstanceName = "NFine";
            });
            var redis = ConnectionMultiplexer.Connect(Configuration.GetConnectionString("RedisConnection"));
            services.AddDataProtection()
                .SetApplicationName("session_application_name")
                .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
            services.AddMemoryCache();//使用本地缓存必须添加
            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromSeconds(7200);//Session过期时间为1小时(60*60)
            });

            services.AddAutoMapper();
            // 添加Cookie服务
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.LoginPath = "/Account/Login";
                options.LogoutPath = "/Account/Logout";
            });
            //services.Configure<CookiePolicyOptions>(options =>
            //{
            //    options.CheckConsentNeeded = context => false;     //这里改成false
            //    options.MinimumSameSitePolicy = SameSiteMode.None;
            //});
            services.AddMvc(option =>
            {
                option.Filters.Add(new LoginAuthFilter());
                //option.Filters.Add<GlobalExceptionFilter>();
                //option.Filters.Add(new OperateLogFilter());
            })
            //全局配置Json序列化处理
            .AddJsonOptions(options =>
            {
                //忽略循环引用
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                //不使用驼峰样式的key
                options.SerializerSettings.ContractResolver = new DefaultContractResolver();
                //设置时间格式
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd hh:mm:ss";
            })
            ;

            #region 注入业务服务类
            //这里可以通过反射的方式批量注入，待优化。
            services.AddTransient(typeof(WxUserService));
            services.AddTransient(typeof(WxAccountService));

            services.AddTransient(typeof(RegionService));
            services.AddTransient(typeof(DictItemService));
            services.AddTransient(typeof(DictService));
            services.AddTransient(typeof(PositionService));
            services.AddTransient(typeof(UserLoginService));
            //services.AddTransient(typeof(OperateLogService));
            services.AddTransient(typeof(OrganizeService));
            services.AddTransient(typeof(PermissionService));
            services.AddTransient(typeof(ResourceService));
            services.AddTransient(typeof(RoleService));
            services.AddTransient(typeof(UserService));
            services.AddTransient(typeof(TenantService));
            #endregion

            services.AddDbContext<NFineDbContext>(options => options.UseMySql(Configuration.GetConnectionString("MySQLConnection")), ServiceLifetime.Transient);
            return services.UseSharpRepository(Configuration.GetSection("sharpRepository"), "efCore");
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }            

            app.UseAuthentication();//使用Cookie的中间件
            app.UseSession();
            app.UseStaticFiles();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
                routes.MapRoute(
                    name: "SystemManage",
                    template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
                routes.MapRoute(
                    name: "SystemSecurity",
                    template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
                routes.MapRoute(
                    name: "WeiXinManage",
                    template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
                routes.MapRoute(
                    name: "ExampleManage",
                    template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
                routes.MapRoute(
                    name: "OAManage",
                    template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
            });

            //app.UseStatusCodePagesWithRedirects("/Errors/Http{0}"); // 绝对路径
            app.UseStaticHttpContext();
            AutoMapperConfig.RegisterMappings();
        }

    }
}
